<?php
// +-------------+-------------+------+-----+---------+----------------+
// | Field       | Type        | Null | Key | Default | Extra          |
// +-------------+-------------+------+-----+---------+----------------+
// | id          | int(11)     | NO   | PRI | NULL    | auto_increment |
// | name        | varchar(50) | YES  |     |         |                |
// | sort_num    | int(11)     | YES  |     | 0       |                |
// | is_hot      | tinyint(1)  | YES  |     | 0       |                |
// | status      | tinyint(1)  | YES  |     | 1       |                |
// | editor_id   | int(11)     | YES  |     | 0       |                |
// | create_time | int(11)     | YES  |     | 0       |                |
// | update_time | int(11)     | YES  |     | 0       |                |
// +-------------+-------------+------+-----+---------+----------------+
namespace app\common\model;
use think\Config;
use think\Loader;
class Tag extends Base{
  protected $auto = ['editor_id'];

  /**
   * 添加或更新关联对象的标签
   * @Author   zhanghong
   * @DateTime 2016-03-13
   * @param    string     $taggable_type 关联对象类型
   * @param    integer    $taggable_id   关联对象ID
   * @param    string/array  $tag_names    关联标签名（如果为空，表示删除taggble对象之前关联的所有标签）
   * @return   array                  操作是否成功
   */
  public function taggble($taggable_type, $taggable_id, $tag_names){
    $res = ["status" => false, "msg" => "标签记录失败"];
    if(empty($taggable_type)){
      $res["msg"] = "Taggable Type不能为空";
      return $res;
    }
    $taggable_type = ucwords($taggable_type);

    $taggable_id = intval($taggable_id);
    if($taggable_id < 1){
      $res["msg"] = "Taggable ID不能为空";
      return $res;
    }
    
    $tag_ids =[];
    if(!empty($tag_names)){
      if(!is_array($tag_names)){
        $tag_names = explode(",", $tag_names);
      }

      $validate = Loader::validate("Tag");
      foreach ($tag_names as $name) {
        $name = trim($name);
        if(empty($name)){
          continue;
        }

        $item = $this->where("name", $name)->find();
        if(empty($item)){
          $data = ["name" => $name];
          if($validate->check($data)){
            $this->isUpdate(false)->data($data)->save();
            $tag_id = $this->id;
          }else{
            // echo("tag error".$validate->getError());
            $tag_id = 0;
          }
        }else{
          $tag_id = $item["id"];
        }
        if($tag_id){
          array_push($tag_ids, $tag_id);
        }
      }
    }
    
    $TaggedModel = new Tagged();
    $validate = Loader::validate("Tagged");
    $excepted_ids = array();
    if(!empty($tag_ids)){
      $tagged_map = array(
        "taggable_type" => $taggable_type,
        "taggable_id" => $taggable_id,
      );
      
      foreach ($tag_ids as $tag_id) {
        $tagged_map["tag_id"] = $tag_id;
        $tagged_item = $TaggedModel->where($tagged_map)->find();
        if(empty($tagged_item)){
          // 新添加的标签
          if($validate->check($tagged_map)){
            $TaggedModel->isUpdate(false)->data($tagged_map)->save();
            array_push($excepted_ids, $TaggedModel->id);
          }else{
            // echo($validate->getError());
          }
        }else{
          // taggble对象之前已有该标签
          array_push($excepted_ids, $tagged_item["id"]);
        }
      }
    }
    
    $delete_map = array(
      "taggable_type" => $taggable_type,
      "taggable_id" => $taggable_id,
    );
    if(!empty($excepted_ids)){
      // 只能删除这次取消的旧标签记录，不能删除和tag_names的关联记录
      $delete_map["id"] = array("NOT IN", $excepted_ids);
    }
    $TaggedModel->where($delete_map)->delete();
    
    return array("status" => true, "msg" => "标签保存成功");
  }

  /**
   * 查询关联对象的标签
   * @Author zhanghong
   * @Date   2017-02-13
   * @param    string     $taggable_type 关联对象类型
   * @param    integer    $taggable_id   关联对象ID
   * @return   array                     标签对象集合
   */
  public function searchByRelatedItem($taggable_type, $taggable_id){
    if(empty($taggable_type)){
      return [];
    }else{
      $this->where("taggable_type", $taggable_type);
    }

    if(intval($taggable_id) < 1){
      return [];
    }else{
      $this->where("taggable_id", $taggable_id);
    }

    $prefix = Config::get("database.prefix");
    $tags = $this->field("{$prefix}tag.id, {$prefix}tag.name")
                 ->join("{$prefix}tagged", "{$prefix}tag.id={$prefix}tagged.tag_id", "INNER")
                 ->order("{$prefix}tag.sort_num DESC, {$prefix}tagged.id")
                 ->select();
    return $tags;
  }

  /**
   * 查询关联对象的标签名
   * @Author   zhanghong
   * @DateTime 2017-02-13
   * @param    string     $taggable_type 关联对象类型
   * @param    integer    $taggable_id   关联对象ID
   * @return   array/false              标签对象集合
   */
  public function searchNameByRelatedItem($taggable_type, $taggable_id){
    $tags = $this->searchByRelatedItem($taggable_type, $taggable_id);
    $names = [];
    foreach ($tags as $t){
      array_push($names, $t["name"]);
    }
    return $names;
  }
}